package com.ubxtech.sentinel.handler;

import cn.hutool.core.util.StrUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson2.JSONObject;
import com.ubxtech.core.context.Result;
import com.ubxtech.core.exception.ErrorCodeCore;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.util.ContentCachingRequestWrapper;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.nio.charset.Charset;

/**
 * BlockException处理返回结果
 * Order注解 要设置数字小一点,要不然BlockException会被 RRExceptionHandler拦截
 * @author Victor.Xiao
 * @since 2023-08-04 17:11
 **/
@RestControllerAdvice
@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE)
public class BlockExceptionHandlerAdvice {

    @ExceptionHandler(BlockException.class)
    public Result<String> handleException(BlockException e) {
        log.error("handle BlockException ExceptionHandler,{}", e.getRule());
        Result<String> result = new Result<>(429,"too many request");
        createResult(result);
        if (StrUtil.isNotBlank(e.getMessage())) {
            result.setMsg(e.getMessage());
        }
        return result;

    }


    /**
     * 发生错误时生成通用返回结果 ,requestBody是在aspect设置
     * @author Victor.Xiao
     * @date 2020-01-19 16:05
     * @param result result
     */
    public void createResult(Result result){
        try{
            // 接收到请求，记录请求内容
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            HttpServletResponse response = attributes.getResponse();
            String method = request.getMethod();
            if ("POST".equals(method)) {
                Object requestBodyObj = request.getAttribute("requestBody");
                if (request instanceof ContentCachingRequestWrapper) {
                    ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;
                    String bodyStr = new String(wrapper.getContentAsByteArray(), Charset.forName(wrapper.getCharacterEncoding()));
                    requestBodyObj = bodyStr;
                    if (StrUtil.isNotBlank(bodyStr) && bodyStr.contains("{")) {
                        JSONObject bodyJson = JSONObject.parseObject(bodyStr);
                        requestBodyObj = bodyJson.toJSONString();

                    }
                }
                log.error("api请求地址,错误请求:url:[{}],request:[{}],response:[{}]", request.getRequestURL(), requestBodyObj, result);

            } else if ("GET".equalsIgnoreCase(method)) {
                Object requestObj = request.getParameterMap();
                log.error("api请求地址,错误请求:url:[{}],request:{},response:[{}]", request.getRequestURL(), JSONObject.toJSONString(requestObj), result);
            }
            response.setStatus(ErrorCodeCore.SENTINEL_EXCEPTION.getHttpStatus());
        }catch (Exception e){
            log.error("createResult error",e);
        }
    }
}
